using System;
using System.Collections.Generic;
using System.Windows.Forms;
using RSSRadio.Model;

namespace RSSRadio
{
	public class SubscriptionListView : CoolListView, ISubscriptionUpdateListener
	{
        public event EventHandler<EventArgs> ListChanged;

        public const string NotLoadedMsg = "Not loaded";
        public const string WaitingMsg = "Retrieving feed...";
        public const string UserWaitUntilLoadedMsg = "Please wait until feeds are loaded.";

        private Dictionary<string, CoolItem> podcastsToList;
        private MenuItem mnuDownloadLatest;

		public bool AllLoaded;

        private bool canDownloadPodcast = false;


        public bool CanDownloadPodcast
        {
            get { return this.canDownloadPodcast; }
        }


		public SubscriptionListView()
			: base()
		{

			this.KeyDown += new KeyEventHandler(SubscriptionListView_KeyDown);
			this.MouseDown += new MouseEventHandler(SubscriptionListView_MouseDown);

			// set up the tap and hold menu
			try
			{
				ContextMenu tapAndHoldMenu = new ContextMenu();
				tapAndHoldMenu.Popup += new EventHandler(tapAndHoldMenu_Popup);
				MenuItem mnuDetails = new MenuItem();
				mnuDetails.Text = "Details";
				mnuDetails.Click += new EventHandler(mnuDetails_Click);
				mnuDownloadLatest = new MenuItem();
				mnuDownloadLatest.Text = "Download Latest Episode";
				mnuDownloadLatest.Click += new EventHandler(mnuDownloadLatest_Click);
				MenuItem mnuDelete = new MenuItem();
				mnuDelete.Text = "Delete";
				mnuDelete.Click += new EventHandler(mnuDelete_Click);

                MenuItem mnuEdit = new MenuItem();
                mnuEdit.Text = "Edit Feed...";
                mnuEdit.Click += new EventHandler(mnuEdit_Click);
                
                tapAndHoldMenu.MenuItems.Add(mnuDetails);
				tapAndHoldMenu.MenuItems.Add(mnuDownloadLatest);
                tapAndHoldMenu.MenuItems.Add(mnuEdit);
                tapAndHoldMenu.MenuItems.Add(mnuDelete);
                this.ContextMenu = tapAndHoldMenu; // throws exception on smartphone
			}
			catch { }
		}
        protected override void SelectedItemIndexChanged()
        {
            SubscriptionManager sm = Globals.getSubscriptionManager();
            CoolItem item = (CoolItem)this.Items[SelectedItemIndex];
            Subscription s = sm.getSubscriptionByURL(item.Tag);
            if (s != null && s.episodes != null && s.episodes.Length > 0)
            {
                canDownloadPodcast = PodcastActions.canDownloadPodcast(s,s.episodes[0]);
            }
            else
            {
                canDownloadPodcast = false;
            }
            mnuDownloadLatest.Enabled = canDownloadPodcast;

            base.SelectedItemIndexChanged();
        }

		void mnuDelete_Click(object sender, EventArgs e)
		{
			DeleteSelectedItem();
            if (ListChanged != null)
            {
                ListChanged(this, new EventArgs());
            }

        }
        void mnuEdit_Click(object sender, EventArgs e)
        {
            EditSelectedItem();
            if (ListChanged != null)
            {
                ListChanged(this, new EventArgs());
            }

        }

		void mnuDownloadLatest_Click(object sender, EventArgs e)
		{
			DownloadSelectedLatestEpisode();
		}

		public bool CheckIfAllLoaded()
		{
			if (!AllLoaded)
				foreach (CoolItem item in Items)
					if (item.Description == WaitingMsg)
						return false;

			return true;
		}


		void mnuDetails_Click(object sender, EventArgs e)
		{
			if (Items.Count == 0)
				return;

			ShowFeedEpisodes();
		}

		void SubscriptionListView_MouseDown(object sender, MouseEventArgs e)
		{
			int itemIndex = (e.Y / ItemHeightPixels) + ScrollBar.Value;

			bool clickedValidItem = IsItemIndexVisible(itemIndex);
			if (clickedValidItem)
				SelectedItemIndex = itemIndex;

			this.Refresh();

			// don't play when called from tap and hold context menu
			if (sender != null && clickedValidItem)
				ShowFeedEpisodes();
		}

		// determines if the supplied item index is visible on the screen. if so, it's OK to highlight
		private bool IsItemIndexVisible(int itemIndex)
		{
			int maxItemsInView = (Items.Count < MaxDisplayableItems) ? Items.Count : MaxDisplayableItems;
			bool visible = (itemIndex < ScrollBar.Value + maxItemsInView);
			return visible;
		}

		void SubscriptionListView_KeyDown(object sender, KeyEventArgs e)
		{
            ProxyKeyDown(e);
		}

        public override void ProxyKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                ShowFeedEpisodes();
            else
            {
                base.ProxyKeyDown(e);
            }
        }

		private void ShowFeedEpisodes()
		{
            SubscriptionManager sm = Globals.getSubscriptionManager();
			if (sm.Count > this.SelectedItemIndex)
			{
                Subscription s = sm.getSubscriptionByURL(((CoolItem)this.Items[SelectedItemIndex]).Tag);
                if (s != null)
                {
                    EpisodeDetails[] episodes = s.episodes;
                    if (episodes != null)
                    {
                        FeedViewerForm fvf = new FeedViewerForm( s);
                        fvf.ShowDialog();
                        return;
                    }
                }
			}

			// error
			MessageBox.Show("Episodes Unavailable.");
		}

		void tapAndHoldMenu_Popup(object sender, EventArgs e)
		{
			SubscriptionListView_MouseDown(null, new MouseEventArgs(MouseButtons.None, 0, 0, this.Parent.PointToClient(MousePosition).Y, 0));
		}

		public void DownloadSelectedLatestEpisode()
		{
            SubscriptionManager sm = Globals.getSubscriptionManager();
            CoolItem item = (CoolItem)this.Items[SelectedItemIndex];
            Subscription s = sm.getSubscriptionByURL(item.Tag);
            if (s != null && s.episodes != null && s.episodes.Length > 0)
            {
                PodcastActions.Download(s,s.episodes[0]);
            }
			else
				MessageBox.Show("Unavailable.");
		}

        public void showDownloadManager()
        {
            DownloadManager downloadMgr = new DownloadManager();
            downloadMgr.ShowDialog();
        }

        #region Feed management
        /// <summary>
        /// Fills the  item list with Subscription information for displaying
        /// </summary>
        public void LoadSubscriptions()
        {
            AllLoaded = false;

            SubscriptionManager feeds = Globals.getSubscriptionManager();

            feeds.addListener(this);

            Items.Clear();
            podcastsToList = new Dictionary<string, CoolItem>();

            foreach (Subscription feed in feeds.Items)
            {
                CoolItem item = new CoolItem();
                SetCoolItemIconAndDescription(item, feed);

                Items.Add(item);

                podcastsToList.Add(feed.URL, item);

            }

            //This should be called in other places
            //feeds.refreshFeeds();
        }

        public void DeleteSelectedItem()
        {
            if (Items.Count == 0)
                return;

            if (CheckIfAllLoaded())
            {
                if (MessageBox.Show("Delete Feed?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                {
                    Globals.getSubscriptionManager().RemoveSubscription(((CoolItem)this.Items[SelectedItemIndex]).Tag);

                    this.Items.RemoveAt(SelectedItemIndex);

                    if (!IsItemIndexVisible(SelectedItemIndex))
                        SelectedItemIndex = 0 + ScrollBar.Value;

                    this.Refresh();
                }
            }
            else
                MessageBox.Show(UserWaitUntilLoadedMsg);
        }

        public void EditSelectedItem()
        {
            if (Items.Count == 0)
                return;

            if (CheckIfAllLoaded())
            {
                Subscription feed = Globals.getSubscriptionManager().getSubscriptionByURL(((CoolItem)this.Items[SelectedItemIndex]).Tag);

                FeedUrlInputDlg feedDlg = new FeedUrlInputDlg(this, feed);
                feedDlg.ShowDialog();

                this.Refresh();
            }
            else
                MessageBox.Show(UserWaitUntilLoadedMsg);

        }


        #endregion

        #region ISubscriptionUpdateListener Members

        private delegate void refreshDelegate();

        public void SubscriptionStateUpdated(string feedURL, FeedState oldState, FeedState newState)
        {
            UpdateCoolItemFromFeed(feedURL);
        }

        public void SubscriptionEpisodeUpdated(string feedURL, string episodeURL, String episodePublishedDate, EpisodeState state)
        {
            UpdateCoolItemFromFeed(feedURL, episodeURL, state);
        }
        public void SubscriptionDetailsUpdated(string feedURL)
        {
            UpdateCoolItemFromFeed(feedURL);
        }

        #endregion

        private void UpdateCoolItemFromFeed(string feedURL)
        {
            UpdateCoolItemFromFeed(feedURL, "", EpisodeState.NewEpisode);
        }

        private void UpdateCoolItemFromFeed(string feedURL, string episodeURL, EpisodeState state)
        {
            SubscriptionManager feeds = Globals.getSubscriptionManager();
            Subscription feed = feeds.getSubscriptionByURL(feedURL);
            CoolItem item = podcastsToList[feed.URL];

            SetCoolItemIconAndDescription(item, feed, episodeURL, state);
            this.Invoke(new refreshDelegate(Refresh));
        }

        private static void SetCoolItemIconAndDescription(CoolItem item, Subscription feed)
        {
            SetCoolItemIconAndDescription(item, feed, "", EpisodeState.NewEpisode);
        }

        private static void SetCoolItemIconAndDescription(CoolItem item, Subscription feed,string episodeUrl, EpisodeState episodeState)
        {
            item.Title = feed.Title;
            item.Tag = feed.URL;
            item.setIconResourceStrings("RSSRadio.graphics.feed.bmp",
                "RSSRadio.graphics.feed32.bmp");
            switch (feed.state)
            {
                case FeedState.LoadPending:
                    item.Description = WaitingMsg;
                    break;
                case FeedState.NotLoaded:
                    item.Description = NotLoadedMsg;
                    break;
                case FeedState.EpisodesLoaded:
                    if (feed.episodes.Length > 0)
                    {
                        item.Description = feed.episodes[0].Title;
                        if (Globals.DownloadedPodcasts.Contains(feed.episodes[0]))
                        {
                            item.setIconResourceStrings("RSSRadio.graphics.feedGray.bmp",
                                "RSSRadio.graphics.feedGray32.bmp");
                        }
                        else if (PodcastActions.IsEpisodeInDownloadQueue( feed.episodes[0]))
                        {
                            item.setIconResourceStrings("RSSRadio.graphics.feedDownload.bmp",
                                "RSSRadio.graphics.feedDownload32.bmp");
                        }
                    }
                    else
                        item.Description = "Unavailable";
                    break;
                case FeedState.Error:
                    item.Description = "Unavailable";
                    break;
                default:
                    break;
            }
        }


    }
}
